#ifndef _CU_FLOAT2_H_
#define _CU_FLOAT2_H_

//**********************************************************************************
// float2 operators and functions
//**********************************************************************************
SDH_CALL float2   operator + (const float2 & u, float v) { float2 r = { u.x + v, u.y + v }; return r; }
SDH_CALL float2   operator - (const float2 & u, float v) { float2 r = { u.x - v, u.y - v }; return r; }
SDH_CALL float2   operator * (const float2 & u, float v) { float2 r = { u.x * v, u.y * v }; return r; }
SDH_CALL float2   operator / (const float2 & u, float v) { float2 r = { u.x / v, u.y / v }; return r; }

SDH_CALL float2   operator + (float v, const float2 & u) { float2 r = { v + u.x, v + u.y }; return r; }
SDH_CALL float2   operator - (float v, const float2 & u) { float2 r = { v - u.x, v - u.y }; return r; }
SDH_CALL float2   operator * (float v, const float2 & u) { float2 r = { v * u.x, v * u.y }; return r; }
SDH_CALL float2   operator / (float v, const float2 & u) { float2 r = { v / u.x, v / u.y }; return r; }

SDH_CALL float2   operator + (const float2 & u, const float2 & v) { float2 r = { u.x + v.x, u.y + v.y }; return r; }
SDH_CALL float2   operator - (const float2 & u, const float2 & v) { float2 r = { u.x - v.x, u.y - v.y }; return r; }
SDH_CALL float2   operator * (const float2 & u, const float2 & v) { float2 r = { u.x * v.x, u.y * v.y }; return r; }
SDH_CALL float2   operator / (const float2 & u, const float2 & v) { float2 r = { u.x / v.x, u.y / v.y }; return r; }

SDH_CALL float2   operator - (const float2 & v) { float2 r = { -v.x, -v.y }; return r; }

SDH_CALL float2 & operator += (float2 & u, const float2 & v) { u.x += v.x; u.y += v.y; return u; }
SDH_CALL float2 & operator -= (float2 & u, const float2 & v) { u.x -= v.x; u.y -= v.y; return u; }
SDH_CALL float2 & operator *= (float2 & u, const float2 & v) { u.x *= v.x; u.y *= v.y; return u; }
SDH_CALL float2 & operator /= (float2 & u, const float2 & v) { u.x /= v.x; u.y /= v.y; return u; }

SDH_CALL float2 & operator += (float2 & u, float v) { u.x += v; u.y += v; return u; }
SDH_CALL float2 & operator -= (float2 & u, float v) { u.x -= v; u.y -= v; return u; }
SDH_CALL float2 & operator *= (float2 & u, float v) { u.x *= v; u.y *= v; return u; }
SDH_CALL float2 & operator /= (float2 & u, float v) { u.x /= v; u.y /= v; return u; }

SDH_CALL float2 catmullrom (const float2 & P0, const float2 & P1, const float2 & P2, const float2 & P3, float t)
{
  const float ts = t * t;
  const float tc = t * ts;

  return (P0 * (-tc + 2.0f * ts - t) + P1 * (3.0f * tc - 5.0f * ts + 2.0f) + P2 * (-3.0f * tc + 4.0f * ts + t) + P3 * ( tc - ts)) * 0.5f;
}
SDH_CALL float2 lerp      (const float2 & u, const float2 & v, float t ) { return u + t * (v - u); }
SDH_CALL float  dot       (const float2 & u, const float2 & v) { return (u.x*v.x + u.y*v.y); }
SDH_CALL float2 clamp     (const float2 & u, float a, float b) { float2 r = { clamp(u.x, a, b), clamp(u.y, a, b) }; return r; }

SDH_CALL float2 saturate  (const float2 & u) { return clamp(u, 0.0f, 1.0f); }

SDH_CALL float2 min (const float2 & u, const float2 & v) { float2 r = {min(u.x, v.x), min(u.y, v.y)}; return r; }
SDH_CALL float2 max (const float2 & u, const float2 & v) { float2 r = {max(u.x, v.x), max(u.y, v.y)}; return r; }

SDH_CALL float  sad (const float2 & u, const float2 & v) { return (abs(u.x - v.x) + abs(u.y - v.y)); } // Sum of Absolute Differences for xy components
SDH_CALL float  ssd (const float2 & u, const float2 & v) { return (sqr(u.x - v.x) + sqr(u.y - v.y)); } // Sum of Squared Differences for xy components

SDH_CALL float2 f2() { float2 r = {0.0f, 0.0f}; return r;}
SDH_CALL float2 f2(float x) { float2 r = {x, x}; return r;}
SDH_CALL float2 f2(float x, float y) { float2 r = {x, y}; return r;}
SDH_CALL float2 f2(const float1 & u, float y) { float2 r = {u.x, y}; return r; }

SDH_CALL float  length    (const float2 & u) { return sqrt(sqr(u.x) + sqr(u.y)); }
SDH_CALL float2 normalize (const float2 & u) { return u / length(u); }

#endif